home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / cp2dekit / samples / wavplay.cpp < prev    next >
C/C++ Source or Header  |  1996-12-29  |  13KB  |  582 lines

  1. //***************************************************************************
  2. //
  3. // this file is (c) '94-'96 Niklas Beisert
  4. //
  5. // this file is part of the cubic player development kit.
  6. // you may only use/modify/spread this file under the terms stated
  7. // in the cubic player development kit accompanying documentation.
  8. //
  9. //***************************************************************************
  10.  
  11.  
  12. // player device example
  13.  
  14. #include <string.h>
  15. #include <dos.h>
  16. #include <conio.h>
  17. #include <stdlib.h>
  18. //#include <io.h>
  19. #include "binfile.h"
  20. #include "poll.h"
  21. #include "player.h"
  22. #include "wave.h"
  23.  
  24. static unsigned char stereo;
  25. static unsigned char bit16;
  26. static unsigned char signedout;
  27. static unsigned long samprate;
  28. static unsigned char reversestereo;
  29.  
  30. static unsigned short *buf16;
  31. static unsigned short __far16 *segbuf16;
  32. static unsigned long bufpos;
  33. static int buflen;
  34. static void *plrbuf;
  35.  
  36. static unsigned short *cliptabl;
  37. static unsigned short *cliptabr;
  38. static unsigned long amplify;
  39. static unsigned long voll,volr;
  40. static char convtostereo;
  41.  
  42. static binfile *wavefile;
  43. static char wavestereo;
  44. static char wave16bit;
  45. static unsigned long waverate;
  46. static unsigned long wavepos;
  47. static unsigned long wavelen;
  48. static unsigned long waveoffs;
  49. static unsigned char *wavebuf;
  50. static unsigned long wavebuflen;
  51. static unsigned long wavebufpos;
  52. static unsigned long wavebuffpos;
  53. static unsigned long wavebufread;
  54. static unsigned long wavebufrate;
  55. static char active;
  56. static char looped;
  57. static char donotloop;
  58. static unsigned long bufloopat;
  59.  
  60. static char pause;
  61.  
  62. extern "C" void mixClipAlt(unsigned short *dst, const unsigned short *src, unsigned long len, const unsigned short *tab);
  63. #pragma aux mixClipAlt parm [edi] [esi] [ecx] [ebx] modify [eax edx]
  64. extern "C" void mixClipAlt2(unsigned short *dst, const unsigned short *src, unsigned long len, const unsigned short *tab);
  65. #pragma aux mixClipAlt2 parm [edi] [esi] [ecx] [ebx] modify [eax edx]
  66.  
  67. signed long muldiv(signed long a, signed long b, unsigned long c);
  68. #pragma aux muldiv parm [eax] [edx] [ebx] value [eax] = "imul edx" "idiv ebx"
  69.  
  70.  
  71. static void mixCalcClipTab(unsigned short *ct, signed long amp)
  72. {
  73.   signed long i,j,a,b;
  74.  
  75.   a=-amp;
  76.   for (i=0; i<256; i++)
  77.     ct[i+768]=(a+=amp)>>16;
  78.  
  79.   for (i=0; i<256; i++)
  80.     ct[i+1024]=0;
  81.  
  82.   b=0x800000-(amp<<7);
  83.   for (i=0; i<256; i++)
  84.   {
  85.     if (b<0x000000)
  86.       if ((b+amp)<0x000000)
  87.       {
  88.         ((unsigned short **)ct)[i]=ct+1024;
  89.         ct[i+512]=0x0000;
  90.       }
  91.       else
  92.       {
  93.         a=0;
  94.         for (j=0; j<256; j++)
  95.         {
  96.           ct[j+1280]=(((a>>8)+b)<0x000000)?0x0000:(((a>>8)+b)>>8);
  97.           a+=amp;
  98.         }
  99.         ((unsigned short **)ct)[i]=ct+1280;
  100.         ct[i+512]=0x0000;
  101.       }
  102.     else
  103.     if ((b+amp)>0xFFFFFF)
  104.       if (b>0xFFFFFF)
  105.       {
  106.         ((unsigned short **)ct)[i]=ct+1024;
  107.         ct[i+512]=0xFFFF;
  108.       }
  109.       else
  110.       {
  111.         a=0;
  112.         for (j=0; j<256; j++)
  113.         {
  114.           ct[j+1536]=(((a>>8)+b)>0xFFFFFF)?0x0000:((((a>>8)+b)>>8)+1);
  115.           a+=amp;
  116.         }
  117.         ((unsigned short **)ct)[i]=ct+1536;
  118.         ct[i+512]=0xFFFF;
  119.       }
  120.     else
  121.     {
  122.       ((unsigned short **)ct)[i]=ct+768;
  123.       ct[i+512]=b>>8;
  124.     }
  125.     b+=amp;
  126.   }
  127. }
  128.  
  129.  
  130. static int clipbusy=0;
  131.  
  132. static void calccliptab(signed long ampl, signed long ampr)
  133. {
  134.   clipbusy++;
  135.  
  136.   if (!stereo)
  137.   {
  138.     ampl=(abs(ampl)+abs(ampr))>>1;
  139.     ampr=0;
  140.   }
  141.  
  142.   mixCalcClipTab(cliptabl, abs(ampl));
  143.   mixCalcClipTab(cliptabr, abs(ampr));
  144.  
  145.   int i;
  146.   if (signedout)
  147.     for (i=0; i<256; i++)
  148.     {
  149.       cliptabl[i+512]^=0x8000;
  150.       cliptabr[i+512]^=0x8000;
  151.     }
  152.  
  153.   clipbusy--;
  154. }
  155.  
  156.  
  157.  
  158. static void timerproc()
  159. {
  160.   if (clipbusy)
  161.     return;
  162.   clipbusy++;
  163.  
  164.   unsigned long bufplayed=plrGetBufPos()>>(stereo+bit16);
  165.   unsigned long bufdelta;
  166.   unsigned long pass2;
  167.   if (bufplayed==bufpos)
  168.   {
  169.     clipbusy--;
  170.     return;
  171.   }
  172.   int quietlen=0;
  173.   bufdelta=(buflen+bufplayed-bufpos)%buflen;
  174.   if (wavebuflen!=wavelen)
  175.   {
  176.     int towrap=muldiv((((wavebuflen+wavebufread-wavebufpos-1)%wavebuflen)>>(wavestereo+wave16bit)), 65536, wavebufrate);
  177.     if (bufdelta>towrap)
  178.       quietlen=bufdelta-towrap;
  179.   }
  180.  
  181.   if (pause)
  182.     quietlen=bufdelta;
  183.  
  184.   int toloop=muldiv(((bufloopat-wavebufpos)>>(wave16bit+wavestereo)), 65536, wavebufrate);
  185.   if (looped)
  186.     toloop=0;
  187.  
  188.   bufdelta-=quietlen;
  189.  
  190.   if (bufdelta>=toloop)
  191.   {
  192.     looped=1;
  193.     if (donotloop)
  194.     {
  195.       quietlen+=bufdelta-toloop;
  196.       bufdelta=toloop;
  197.     }
  198.   }
  199.  
  200.   if (bufdelta)
  201.   {
  202.     if ((bufpos+bufdelta)>buflen)
  203.       pass2=bufpos+bufdelta-buflen;
  204.     else
  205.       pass2=0;
  206.     plrClearBuf(buf16, bufdelta*2, 1);
  207.  
  208.     int i;
  209.     if (wave16bit)
  210.     {
  211.       if (wavestereo)
  212.         for (i=0; i<bufdelta; i++)
  213.         {
  214.           unsigned long v=*(unsigned long*)(wavebuf+wavebufpos)^0x80008000;
  215.           if (reversestereo)
  216.             v=_lrotl(v, 16);
  217.           *(unsigned long*)(buf16+2*i)=v;
  218.           wavebuffpos+=wavebufrate;
  219.           wavebufpos+=(wavebuffpos>>16)*4;
  220.           wavebuffpos&=0xFFFF;
  221.           if (wavebufpos>=wavebuflen)
  222.             wavebufpos-=wavebuflen;
  223.         }
  224.       else
  225.         for (i=0; i<bufdelta; i++)
  226.         {
  227.           buf16[2*i+1]=buf16[2*i]=*(unsigned short*)(wavebuf+wavebufpos)^0x8000;
  228.           wavebuffpos+=wavebufrate;
  229.           wavebufpos+=(wavebuffpos>>16)*2;
  230.           wavebuffpos&=0xFFFF;
  231.           if (wavebufpos>=wavebuflen)
  232.             wavebufpos-=wavebuflen;
  233.         }
  234.     }
  235.     else
  236.     {
  237.       if (wavestereo)
  238.         for (i=0; i<bufdelta; i++)
  239.         {
  240.           if (reversestereo)
  241.           {
  242.             buf16[2*i+1]=wavebuf[wavebufpos]<<8;
  243.             buf16[2*i]=wavebuf[wavebufpos+1]<<8;
  244.           }
  245.           else
  246.           {
  247.             buf16[2*i]=wavebuf[wavebufpos]<<8;
  248.             buf16[2*i+1]=wavebuf[wavebufpos+1]<<8;
  249.           }
  250.           wavebuffpos+=wavebufrate;
  251.           wavebufpos+=(wavebuffpos>>16)*2;
  252.           wavebuffpos&=0xFFFF;
  253.           if (wavebufpos>=wavebuflen)
  254.             wavebufpos-=wavebuflen;
  255.         }
  256.       else
  257.         for (i=0; i<bufdelta; i++)
  258.         {
  259.           buf16[2*i+1]=buf16[2*i]=wavebuf[wavebufpos]<<8;
  260.           wavebuffpos+=wavebufrate;
  261.           wavebufpos+=wavebuffpos>>16;
  262.           wavebuffpos&=0xFFFF;
  263.           if (wavebufpos>=wavebuflen)
  264.             wavebufpos-=wavebuflen;
  265.         }
  266.     }
  267.  
  268.     if (!stereo)
  269.     {
  270.       for (i=0; i<bufdelta; i++)
  271.         buf16[i]=(buf16[2*i]+buf16[2*i+1])>>1;
  272.     }
  273.  
  274.     if (bit16)
  275.     {
  276.       if (stereo)
  277.       {
  278.         mixClipAlt2((unsigned short*)plrbuf+bufpos*2, buf16, bufdelta-pass2, cliptabl);
  279.         mixClipAlt2((unsigned short*)plrbuf+bufpos*2+1, buf16+1, bufdelta-pass2, cliptabr);
  280.         if (pass2)
  281.         {
  282.           mixClipAlt2((unsigned short*)plrbuf, buf16+2*(bufdelta-pass2), pass2, cliptabl);
  283.           mixClipAlt2((unsigned short*)plrbuf+1, buf16+2*(bufdelta-pass2)+1, pass2, cliptabr);
  284.         }
  285.       }
  286.       else
  287.       {
  288.         mixClipAlt((unsigned short*)plrbuf+bufpos, buf16, bufdelta-pass2, cliptabl);
  289.         if (pass2)
  290.           mixClipAlt((unsigned short*)plrbuf, buf16+bufdelta-pass2, pass2, cliptabl);
  291.       }
  292.     }
  293.     else
  294.     {
  295.       if (stereo)
  296.       {
  297.         mixClipAlt2(buf16, buf16, bufdelta, cliptabl);
  298.         mixClipAlt2(buf16+1, buf16+1, bufdelta, cliptabr);
  299.       }
  300.       else
  301.         mixClipAlt(buf16, buf16, bufdelta, cliptabl);
  302.       plr16to8((unsigned char*)plrbuf+(bufpos<<stereo), buf16, (bufdelta-pass2)<<stereo);
  303.       if (pass2)
  304.         plr16to8((unsigned char*)plrbuf, buf16+((bufdelta-pass2)<<stereo), pass2<<stereo);
  305.     }
  306.     bufpos+=bufdelta;
  307.     if (bufpos>=buflen)
  308.       bufpos-=buflen;
  309.   }
  310.  
  311.   bufdelta=quietlen;
  312.   if (bufdelta)
  313.   {
  314.     if ((bufpos+bufdelta)>buflen)
  315.       pass2=bufpos+bufdelta-buflen;
  316.     else
  317.       pass2=0;
  318.     if (bit16)
  319.     {
  320.       plrClearBuf((unsigned short*)plrbuf+(bufpos<<stereo), (bufdelta-pass2)<<stereo, !signedout);
  321.       if (pass2)
  322.         plrClearBuf((unsigned short*)plrbuf, pass2<<stereo, !signedout);
  323.     }
  324.     else
  325.     {
  326.       plrClearBuf(buf16, bufdelta<<stereo, !signedout);
  327.       plr16to8((unsigned char*)plrbuf+(bufpos<<stereo), buf16, (bufdelta-pass2)<<stereo);
  328.       if (pass2)
  329.         plr16to8((unsigned char*)plrbuf, buf16+((bufdelta-pass2)<<stereo), pass2<<stereo);
  330.     }
  331.     bufpos+=bufdelta;
  332.     if (bufpos>=buflen)
  333.       bufpos-=buflen;
  334.   }
  335.  
  336.   plrAdvanceTo(bufpos<<(stereo+bit16));
  337.   clipbusy--;
  338. }
  339.  
  340.  
  341.  
  342.  
  343. void wpIdle()
  344. {
  345.   if ((wavelen==wavebuflen)||!active)
  346.     return;
  347.  
  348.   unsigned long clean=(wavebufpos+wavebuflen-wavebufread)%wavebuflen;
  349.   if (clean*8>wavebuflen)
  350.   {
  351.     while (clean)
  352.     {
  353.       wavefile->seek(waveoffs+wavepos);
  354.       int read=clean;
  355.       if ((wavebufread+read)>wavebuflen)
  356.         read=wavebuflen-wavebufread;
  357.       if ((wavepos+read)>=wavelen)
  358.       {
  359.         read=wavelen-wavepos;
  360.         bufloopat=wavebufread+read;
  361.       }
  362.       if (read>0x10000)
  363.         read=0x10000;
  364.       wavefile->read(wavebuf+wavebufread, read);
  365.       wavebufread=(wavebufread+read)%wavebuflen;
  366.       wavepos=(wavepos+read)%wavelen;
  367.       clean-=read;
  368.     }
  369.   }
  370. }
  371.  
  372. unsigned char wpOpenPlayer(binfile &wav, int tostereo)
  373. {
  374.   if (!plrPlay)
  375.     return 0;
  376.  
  377.   convtostereo=tostereo;
  378.  
  379.   cliptabl=new unsigned short[1793];
  380.   cliptabr=new unsigned short[1793];
  381.  
  382.   if (!cliptabl||!cliptabr)
  383.   {
  384.     delete cliptabl;
  385.     delete cliptabr;
  386.     return 0;
  387.   }
  388.  
  389.   wavefile=&wav;
  390.  
  391.   if (wavefile->getul()!=0x46464952)
  392.     return 0;
  393.   wavefile->getul();
  394.   if (wavefile->getul()!=0x45564157)
  395.     return 0;
  396.   while (1)
  397.   {
  398.     int stat;
  399.     if (wavefile->egetul(stat)==0x20746D66)
  400.       break;
  401.     if (!stat)
  402.       return 0;
  403.     wavefile->seekcur(wavefile->getul());
  404.   }
  405.   if (wavefile->getul()!=16)
  406.     return 0;
  407.   if (wavefile->getus()!=1)
  408.     return 0;
  409.   wavestereo=wavefile->getus()==2;
  410.   waverate=wavefile->getul();
  411.   wavefile->getul();
  412.   wavefile->getus();
  413.   wave16bit=wavefile->getus()==16;
  414.  
  415.   while (1)
  416.   {
  417.     int stat;
  418.     if (wavefile->egetul(stat)==0x61746164)
  419.       break;
  420.     if (!stat)
  421.       return 0;
  422.     wavefile->seekcur(wavefile->getul());
  423.   }
  424.   wavelen=wavefile->getul();
  425.   waveoffs=wavefile->tell();
  426.   if (!wavelen)
  427.     return 0;
  428.   wavebuflen=1024*1024;
  429.   if (wavebuflen>wavelen)
  430.   {
  431.     wavebuflen=wavelen;
  432.     bufloopat=wavebuflen;
  433.   }
  434.   else
  435.     bufloopat=0x40000000;
  436.   wavebuf=new unsigned char [wavebuflen];
  437.   if (!wavebuf)
  438.   {
  439.     wavebuflen=256*1024;
  440.     wavebuf=new unsigned char [wavebuflen];
  441.     if (!wavebuf)
  442.       return 0;
  443.   }
  444.   wavelen=wavelen&~(1<<(wavestereo+wave16bit)-1);
  445.   wavebufpos=0;
  446.   wavebuffpos=0;
  447.   wavebufread=0;
  448.  
  449.   wavefile->read(wavebuf, wavebuflen);
  450.   wavepos=wavebuflen;
  451.  
  452.   plrSetOptions(waverate, (convtostereo||wavestereo)?(PLR_STEREO|PLR_16BIT):PLR_16BIT);
  453.  
  454.   if (!plrOpenPlayer(plrbuf, buflen))
  455.     return 0;
  456.  
  457.   stereo=!!(plrOpt&PLR_STEREO);
  458.   bit16=!!(plrOpt&PLR_16BIT);
  459.   signedout=!!(plrOpt&PLR_SIGNEDOUT);
  460.   reversestereo=!!(plrOpt&PLR_REVERSESTEREO);
  461.   samprate=plrRate;
  462.  
  463.   wavebufrate=muldiv(65536, waverate, samprate);
  464.  
  465.   pause=0;
  466.   looped=0;
  467.   amplify=65536;
  468.   voll=256;
  469.   volr=256;
  470.   calccliptab((amplify*voll)>>8, (amplify*volr)>>8);
  471.  
  472.   buf16=new unsigned short [buflen*2];
  473.  
  474.   if (!buf16)
  475.   {
  476.     plrClosePlayer();
  477.     delete buf16;
  478.     return 0;
  479.   }
  480.  
  481.   bufpos=0;
  482.  
  483.   if (!pollInit(timerproc))
  484.   {
  485.     plrClosePlayer();
  486.     return 0;
  487.   }
  488.  
  489.   active=1;
  490.  
  491.   return 1;
  492. }
  493.  
  494. void wpClosePlayer()
  495. {
  496.   active=0;
  497.  
  498.   pollClose();
  499.  
  500.   plrClosePlayer();
  501.  
  502.   delete wavebuf;
  503.   delete buf16;
  504.  
  505.   delete cliptabl;
  506.   delete cliptabr;
  507. }
  508.  
  509. char wpLooped()
  510. {
  511.   return looped;
  512. }
  513.  
  514. void wpSetLoop(unsigned char s)
  515. {
  516.   donotloop=!s;
  517. }
  518.  
  519. void wpPause(unsigned char p)
  520. {
  521.   pause=p;
  522. }
  523.  
  524. void wpSetAmplify(unsigned long amp)
  525. {
  526.   amplify=amp;
  527.   calccliptab((amplify*voll)>>8, (amplify*volr)>>8);
  528. }
  529.  
  530. void wpSetSpeed(unsigned short sp)
  531. {
  532.   if (sp<32)
  533.     sp=32;
  534.   wavebufrate=muldiv(256*sp, waverate, samprate);
  535. }
  536.  
  537. void wpSetVolume(unsigned char vol, signed char bal, signed char pan, unsigned char opt)
  538. {
  539.   voll=vol*4;
  540.   volr=vol*4;
  541.   if (bal<0)
  542.     volr=(volr*(64+bal))>>6;
  543.   else
  544.     voll=(voll*(64-bal))>>6;
  545.   wpSetAmplify(amplify);
  546. }
  547.  
  548. unsigned long wpGetPos()
  549. {
  550.   if (wavelen==wavebuflen)
  551.     return wavebufpos>>(wavestereo+wave16bit);
  552.   else
  553.     return ((wavepos+wavelen-wavebuflen+((wavebufpos-wavebufread+wavebuflen)%wavebuflen))%wavelen)>>(wavestereo+wave16bit);
  554. }
  555.  
  556. void wpGetInfo(waveinfo &i)
  557. {
  558.   i.pos=wpGetPos();
  559.   i.len=wavelen>>(wavestereo+wave16bit);
  560.   i.rate=waverate;
  561.   i.stereo=wavestereo;
  562.   i.bit16=wave16bit;
  563. }
  564.  
  565. void wpSetPos(signed long pos)
  566. {
  567.   pos=((pos<<(wave16bit+wavestereo))+wavelen)%wavelen;
  568.   if (wavelen==wavebuflen)
  569.     wavebufpos=pos;
  570.   else
  571.   {
  572.     if (((pos+wavebuflen)>wavepos)&&(pos<wavepos))
  573.       wavebufpos=(wavebufread-(wavepos-pos)+wavebuflen)%wavebuflen;
  574.     else
  575.     {
  576.       wavepos=pos;
  577.       wavebufpos=0;
  578.       wavebufread=1<<(wave16bit+wavestereo);
  579.     }
  580.   }
  581. }
  582.